//
//  ZYSignalExceptionHandler.m
//  ZYWebImage
//
//  Created by wangzhipan on 2025/5/3.
//

#import "ZYSignalExceptionHandler.h"
#import "ZYCrashReportGenerator.h"
#import <signal.h>
#import <execinfo.h>

// 定义要捕获的信号数组
static const int _signalsToHandle[] = {
    SIGABRT,    // 由abort()函数触发，常见于断言失败或调用abort
    SIGBUS,     // 总线错误，通常是内存对齐问题
    SIGFPE,     // 浮点异常，如除零错误
    SIGILL,     // 非法指令，CPU无法识别的指令
    SIGPIPE,    // 管道破裂，写入到已关闭的管道或socket
    SIGSEGV,    // 段错误，非法内存访问，最常见的崩溃类型
    SIGSYS,     // 无效的系统调用
    SIGTRAP,    // 断点陷阱，通常由调试器使用
};

// 信号数量
static int _signalCount = sizeof(_signalsToHandle) / sizeof(_signalsToHandle[0]);

// 保存原始的信号处理函数，用于卸载时恢复
static struct sigaction _previousSignalHandlers[32];

static bool _isHandlerInstalled = false;              //处理器安装状态标志

/**
 * 获取信号名称
 * @param signal 信号编号
 * @return 信号的字符串表示
 */
static const char* signalName(int signal) {
    switch (signal) {
        case SIGABRT: return "SIGABRT"; // 异常终止
        case SIGBUS:  return "SIGBUS";  // 总线错误
        case SIGFPE:  return "SIGFPE";  // 浮点异常
        case SIGILL:  return "SIGILL";  // 非法指令
        case SIGPIPE: return "SIGPIPE"; // 管道破裂
        case SIGSEGV: return "SIGSEGV"; // 段错误
        case SIGSYS:  return "SIGSYS";  // 无效系统调用
        case SIGTRAP: return "SIGTRAP"; // 断点陷阱
        default:      return "UNKNOWN"; // 未知信号
    }
}

/**
 * 获取信号描述
 * @param signal 信号编号
 * @return 信号的详细描述
 */
static const char* signalDescription(int signal) {
    switch (signal) {
        case SIGABRT: return "程序异常终止，通常由abort()函数触发";
        case SIGBUS:  return "总线错误，通常是访问未对齐的内存地址";
        case SIGFPE:  return "浮点运算错误，如除零或浮点溢出";
        case SIGILL:  return "非法指令，CPU无法识别的指令";
        case SIGPIPE: return "管道破裂，写入到已关闭的管道或socket";
        case SIGSEGV: return "段错误，访问无效的内存地址";
        case SIGSYS:  return "无效的系统调用参数";
        case SIGTRAP: return "断点陷阱，通常由调试器使用";
        default:      return "未知信号";
    }
}

/**
 * 信号处理函数
 * 当进程收到指定信号时，系统会调用此函数
 * @param signalReceived 接收到的信号编号
 * @param info 信号的详细信息
 * @param context 进程上下文，包含寄存器状态等
 */
static void handleSignal(int signalReceived, siginfo_t *info, void *context)
{
    // 防止递归崩溃，忽略后续信号
    // 在信号处理函数中再次发生崩溃是很危险的
    struct sigaction sa;
    
    // 正确设置默认处理器
    sa.__sigaction_u.__sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    
    // 为所有捕获的信号重置为默认处理器
    for (int i = 0; i < _signalCount; i++) {
        sigaction(_signalsToHandle[i], &sa, NULL);
    }
    
    // 构建异常名称和原因
    NSString *name = [NSString stringWithFormat:@"%s", signalName(signalReceived)];
    NSString *reason = [NSString stringWithFormat:@"信号异常: %s (%s)", signalName(signalReceived), signalDescription(signalReceived)];
    
    // 收集额外信息
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    userInfo[@"signal"] = @(signalReceived);
    
    // 如果有信号详情，记录错误地址
    if (!info) {
        userInfo[@"address"] = [NSValue valueWithPointer:info->si_addr];
        userInfo[@"code"] = @(info->si_code);
    }
    
    // 获取调用栈
    void *callStack[128];
    int frames = backtrace(callStack, 128);
    char **symbols = backtrace_symbols(callStack, frames);
    
    if (symbols) {
        NSMutableArray *stackTree = [NSMutableArray arrayWithCapacity:frames];
        for (int i = 0; i < frames; i++) {
            [stackTree addObject:[NSString stringWithUTF8String:symbols[i]]];
        }
        userInfo[@"callStack"] = stackTree;
        free(symbols);
    }
    
    // 生成崩溃报告
    [[ZYCrashReportGenerator sharedInstance] generateReportWithType:ZYCrashTypeSignal
                                                               name:name
                                                             reason:reason
                                                           userInfo:userInfo];
    
    // 终止应用程序
    // 使用默认的信号处理行为，确保进程终止
    struct sigaction stop_sa;
    stop_sa.__sigaction_u.__sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(signalReceived, &stop_sa, NULL);
    
    // 向自身重新发送信号，触发默认处理行为
    kill(getpid(), signalReceived);
}

@implementation ZYSignalExceptionHandler
- (BOOL)install
{
    if (_isHandlerInstalled) {
        return YES;
    }
    
    @synchronized (self) {
        if (_isHandlerInstalled) {
            return YES;
        }
        
        // 设置信号处理结构体
        struct sigaction sa;
        /*
         #define sa_handler      __sigaction_u.__sa_handler
         #define sa_sigaction    __sigaction_u.__sa_sigaction
         */
        sa.__sigaction_u.__sa_sigaction = handleSignal;         //设置信号处理函数
        sa.sa_flags = SA_SIGINFO;       //使用sa_sigaction字段而不是sa_handler
        
        //初始化信号集，确保在处理一个信号时不会被其他信号中断
        sigemptyset(&sa.sa_flags);
        for (int i = 0; i < _signalCount; i++) {
            sigaddset(&sa.sa_flags, _signalsToHandle[i]);
        }
        
        //注册信号处理函数
        for (int i = 0; i < _signalCount; i++) {
            int signal = _signalsToHandle[i];
            //保存原始处理器，用于卸载时恢复
            if (sigaction(signal, NULL, &_previousSignalHandlers[signal]) == 0) {
                
                /*
                 sigaction(signum, act,oldact)函数说明：
                 - signum ：要设置处理行为的信号编号

                    - 例如 SIGABRT 、 SIGSEGV 、 SIGBUS 等
                    - 不能用于 SIGKILL 和 SIGSTOP （这两个信号不能被捕获或忽略）
                 
                 - act ：指向新的信号处理配置的指针

                    - 如果为 NULL ，则不改变当前信号处理行为
                    - 包含信号处理函数、信号掩码和处理标志等信息
                 
                 - oldact ：用于保存原有信号处理配置的指针

                    - 如果为 NULL ，则不保存原有配置
                    - 可用于之后恢复原有的信号处理行为
                 */
                
                //只有在成功获取原始处理器后才设置新的处理器
                if (sigaction(signal, &sa, NULL) != 0) {
                    NSLog(@"Failed to register handler for signal %d (%s)", signal, signalName(signal));
                    // 发生错误时恢复已设置的处理器
                    for (int j = 0; j < i; j++) {
                        sigaction(_signalsToHandle[j], &_previousSignalHandlers[_signalsToHandle[j]], NULL);
                    }
                    return NO;
                }
            }
            else {
                NSLog(@"Failed to get previous handler for signal %d (%s)", signal, signalName(signal));
                // 发生错误时恢复已设置的处理器
                for (int j = 0; j < i; j++) {
                    sigaction(_signalsToHandle[j], &_previousSignalHandlers[_signalsToHandle[j]], NULL);
                }
                return NO;
            }
        }
    }
    
    _isHandlerInstalled = YES;
    return YES;
}

- (void)uninstall
{
    @synchronized (self) {
        if (!_isHandlerInstalled) {
            return;
        }
        
        //恢复原始的信号处理器
        for (int i = 0; i < _signalCount; i++) {
            int signal = _signalsToHandle[i];
            sigaction(signal, &_previousSignalHandlers[signal], NULL);
        }
    }
    _isHandlerInstalled = NO;
}
@end
